from flask import Blueprint,jsonify,g
from flask_restful import Api,Resource,reqparse,marshal
from models.users import *
from models.channel import *
from werkzeug.security import generate_password_hash,check_password_hash
from models import db
from common.send_sms_code import sms_code
import json,redis,random,datetime
from utils.jwt_util import generate_token,_generate_token
from utils.redis_client import RedisOper
from models_fields.user_f import *
from utils.login_utils import login_required
from utils.qiniu_file import qiniu_token


user_bp = Blueprint('user_bp',__name__,url_prefix='/users')
api = Api(user_bp)


# 注册
class Register(Resource):
    def post(self):
        parse = reqparse.RequestParser()
        parse.add_argument('username')  #账号
        parse.add_argument('password')  #密码
        parse.add_argument('mobile')    #手机号
        parse.add_argument('nickname')  #昵称
        parse.add_argument('confirmpassword')   #确认密码

        args = parse.parse_args()
        uname = args.get('username')
        password = args.get('password')
        nick_name = args.get('nickname')
        mobile = args.get('mobile')
        confirm_pwd = args.get('confirmpassword')

        print('AAAA',parse,type(parse))
        print('BBBB',args,type(args))
        print('CCCC',args.get,type(args.get))
        print('DDDD', args.get('comfirmpassword'))
        print('密码1',password,'密码2',confirm_pwd)

        if len(uname) > 32:
            return jsonify(code=400,msg='账号太长')
        if password != confirm_pwd:
            return jsonify(code=400,msg='两次密码不一致')
        user = User.query.filter_by(mobile=mobile).count()
        if user >= 1:
            return jsonify(code=400,msg='手机号已注册')

        try:
            pash_pwd = generate_password_hash(password)
            users = User(mobile=mobile,account=uname,password=pash_pwd,uname=nick_name)
            db.session.add(users)
            db.session.commit()
            return jsonify(code=200,msg='注册成功')
        except Exception as e:
            print('注册失败的错误信息',e)
            return jsonify(code=204,msg='注册失败')

# 获取短信验证码
class SendSMSCode(Resource):
    def post(self):
        parse = reqparse.RequestParser()
        parse.add_argument('mobile')
        args = parse.parse_args()
        mobile = args.get('mobile')

        user_mobile = User.query.filter_by(mobile=mobile).first()

        if not user_mobile:
            return jsonify(code=204,msg='该手机号不存在')
        key_ = '%s'%mobile
        sms = random.randint(1000, 9999)

        # rest = sms_code.delay(sms,mobile)   #使用容联云
        # if rest:
        #     conn = redis.Redis(host='localhost',port=6379,password='wang123',db=0)
        #             # conn.setex('sms_%s'%mobile,60,sms)
        #     conn.set(key_,sms,ex=600)
        #     return jsonify(code=200,msg='短信验证码发送成功,请注意查收')
        # else:
        #     return jsonify(code=204,msg='获取短信失败')

        # try:  #自己写的
        #     conn = redis.Redis(host='localhost', port=6379, password='wang123', db=0)
        #     conn.set(key_, sms, ex=300)
        #     print('获取的短信验证码',sms)
        #     return jsonify(code=200, msg='短信验证码发送成功,请注意查收',sms_code=sms)
        # except Exception as e:
        #     print('获取短信验证码错误',e)
        #     return jsonify(code=204, msg='获取短信失败')


        try:    #老师的方式
            rds = RedisOper()
            rds.set_v(mobile,sms,ex=300)
            print('获取的短信验证码',sms)
            return jsonify(message="短信验证码发送成功", code=200,sms_code=sms)
        except Exception as e:
            print('获取短信验证码错误', e)
            return jsonify(message='短线验证码发送失败', code=500)


# 登录
class Login(Resource):
    def post(self):
        parse = reqparse.RequestParser()
        parse.add_argument('mobile')
        parse.add_argument('sms')
        args = parse.parse_args()
        mobile = args.get('mobile')
        sms = args.get('sms')

        if not all([mobile,sms]):
            return jsonify(code=204,msg='登录信息不完整')

        rds = RedisOper()
        origin_sms_code = rds.get_v(mobile)
        if not origin_sms_code:
            return jsonify(msg='验证码已过期', code=500)
        if sms.encode() != origin_sms_code:
            return jsonify(msg='验证码不正确', code=400)

        try:
            user = User.query.filter_by(mobile=mobile).first()
            if not user:
                return jsonify(code=204, msg='此手机号未注册')



            data = {
                'user':user.account,
                'id':user.uid
            }
            # expiry = datetime.timedelta(hours=2)    #生成token需要的 时间
            # token = generate_token(data,str(expiry))    #给生成token的方法传值
            token,refresh_token = _generate_token(data,is_refresh=True)
            if token:   #有token 构造给前端传的数据
                data_={
                    'user_id':user.uid,
                    'token':token,
                    'refresh_token': refresh_token
                }
                return jsonify(code=200,msg='登录成功',data=data_)

            return jsonify(code=500,msg='token生成失败')
        except Exception as e:
            print('登陆失败的错误',e)
            return jsonify(code=204,msg='登陆失败')


# 登录用户信息
class UserInfo(Resource):
    # 获取登录用户信息
    @login_required
    def get(self,id):
        user = User.query.filter_by(uid=id).first()
        if user:
            user_f = marshal(user,user_fields)
            return jsonify(code=200,msg='用户信息',data=user_f)

    # 修改登录用户信息
    @login_required
    def put(self,id):
        parse = reqparse.RequestParser()
        parse.add_argument('head_img')
        parse.add_argument('uname')
        parse.add_argument('password')
        parse.add_argument('gender')
        args = parse.parse_args()
        profile_photo = args.get('head_img')
        uname = args.get('uname')
        password = args.get('password')
        gender = args.get('gender')
        if profile_photo:
            # 修改头像
            User.query.filter_by(uid=g.id).update({'profile_photo': profile_photo})
            db.session.commit()
            return jsonify(message="修改头像成功", code=200)
        if uname:
            User.query.filter_by(uid=id).update({'uname':uname})
            db.session.commit()
            return jsonify(code=200, msg='修改昵称成功')
        if gender:
            User.query.filter_by(uid=id).update({'gender': gender})
            db.session.commit()
            return jsonify(code=200, msg='修改班级成功')
        if password:
            pwd_hash = generate_password_hash(password)
            User.query.filter_by(uid=id).update({'password': pwd_hash})
            db.session.commit()

            # 在这里生成新token
            data={
                'id':g.id
            }
            token,refresh_token = _generate_token(data)
            # 把新生成的token写入redis
            res = redis.Redis()
            res.set('user:%s:token'%(g.id),token,2*60*60)
            return jsonify(msg="修改密码成功", code=200)
                # data={'token': token, 'id': g.user_id, 'refresh_token': refresh_token)


# 登录用户的关注   用户
class Follow_User(Resource):
    @login_required     #获取关注的用户
    def get(self):
        uid = g.id
        try:    #查找用户关注的所有用户
            relation = Relation.query.filter_by(user_id=uid).all()
            # print('AAA',relation)
            list1=[]
            for foller in relation:
                # print('BBB', foller, foller.foller_id)
                if foller.relation:
                    user_rel = User.query.filter_by(uid=foller.foller_id).first()
                    user_rel_f = marshal(user_rel,user_fields)
                    list1.append(user_rel_f)
            return jsonify(code=200,msg='获取关注成功',data=list1)
        except Exception as e:
            print('获取关注用户错误',e)
            return jsonify(code=200,msg='获取登录用户关注失败')

    @login_required     #取消关注用户
    def put(self):
        parse = reqparse.RequestParser()
        parse.add_argument('foller_id')
        args = parse.parse_args()
        foller_id = args.get('foller_id')
        uid = g.id
        print('AAA',uid,foller_id)
        try:
            Relation.query.filter_by(user_id=uid,foller_id=foller_id).update({'relation':False})
            db.session.commit()
            return jsonify(code=200,msg='取消关注成功')
        except Exception as e:
            print('错误',e)
            return jsonify(code=204)


# 登录用户关注    的频道
class UserChannels(Resource):
    @login_required     # 获取登录用户关注的频道
    def get(self):
        uid = g.id
        try:    #查找用户信息
            user = User.query.filter_by(uid=uid).first()
            channels = user.channels    #根据用户信息 查找关注的频道信息
            list1=[]
            for i in channels:      #循环出每个频道信息
                print('单个频道',marshal(i,channel_fields))
                #查找中间表的  用户关注 的  频道 的单条数据
                user_channel = UserChannel.query.filter_by(uid=uid,cid=i.cid).first()
                if user_channel.is_delete: # 判断 这条信息 的 is_delete 的值 是 False 还是 True
                    channel_f = marshal(i,channel_fields)
                    list1.append(channel_f)
                    # print('频道数据',list1)
            return jsonify(code=200,msg='获取用户关注频道成功',data=list1)
        except Exception as e:
            print('获取关注频道信息错误',e)
            return jsonify(code=200,msg='获取用户关注频道错误')

    @login_required   # 取消登录用户关注的频道
    def put(self):
        parse = reqparse.RequestParser()
        parse.add_argument('cid')
        args = parse.parse_args()
        cid = args.get('cid')
        try:
            uid = g.id
            UserChannel.query.filter_by(uid=uid,cid=cid).update({'is_delete':False})
            db.session.commit()
            return jsonify(code=200,msg='取消关注频道成功')
        except Exception as e:
            print('取消关注频道失败',e)
            return jsonify(code=204,msg='取消关注频道失败')



# 登录用户收藏    的文章
class Collect_News(Resource):
    @login_required     #获取登录用户的收藏文章 及作者信息
    def get(self):
        uid = g.id
        user = User.query.filter_by(uid=uid).first()    #查找登录用户
        news = user.collections     #获取收藏文章
        list1=[]
        for new in news:    #循环每个文章
            user_n = User.query.filter_by(uid=new.user_id).first()  #查找每个文章的作者
            data = {
                'user':{'nickname':user_n.uname},
                'title':new.title,
                'comment_length':new.comment_count,
            }
            list1.append(data)
        return jsonify(code=200,msg='获取收藏文章',data=list1)


# 获取登录用户的跟帖
class UserComments(Resource):
    @login_required
    def get(self):
        uid = g.id
        user = User.query.filter_by(uid=uid).first()  # 查找登录用户信息
        comment = user.comment  #用户的 每个评论
        list1=[]
        for i in comment:   #循环每个评论
            news = i.article    #查找 评论的文章信息
            parent =Comment.query.filter_by(cmid=i.parent_id).first()   #查找 被回复的评论信息
            parent_user=parent.comments  #查找 评论的评论的用户信息

            data={
                'id':i.cmid,
                'create_date':i.ctime,
                'content':i.content,
                'title':news.title,
                'post':{
                    'title':news.title
                    },
                'parent':{
                    'create_date':parent.ctime,
                    'content':parent.content,
                    'user':{
                        'nickname':parent_user.uname
                        }
                    }
                }
            list1.append(data)
        return jsonify(code=200,msg='查询评论成功',data=list1)

        # try:
        #     id = g.id  # 获取该用户id
        #     user = User.query.filter_by(uid=id).first()  # 获取该用户对象
        #     comment = user.comment  # 获取该用户的所有评论
        #     comments = marshal(comment, comment_fields)  # 序列化所有评论
        #     for i in comments:  # 循环每个评论字典
        #         news = News.query.filter_by(nid=i.get('article_id')).first()  # 找到每个评论评论文章
        #         i['post'] = marshal(news, news_fields)  # 将每个评论的文章写入评论字典    是对文章的评论
        #         if i.get('parent_id'):  # 如果评论的不是文章 而是别人的评论
        #             com = Comment.query.get(i.get('parent_id'))  # 找到这个被评论的评论对象
        #             user = User.query.get(com.user_id)  # 找到这个被评论的用户
        #             com_f = marshal(com, comment_fields)  # 序列化这个评论对象
        #             user_f = marshal(user, user_fields)  # 序列化这个用户
        #             com_f['user'] = user_f  # 将这个用户字典加到被评论字典中
        #             i['parent'] = com_f  # 将被评论的字典加到 每个我评论的字典  是对评论的评论
        #     return jsonify(code=200, msg='获取跟帖成功', data=comments)  # 返回我所有的评论字典
        # except Exception as e:
        #     print('获取跟帖的错误', e)
        #     return jsonify(code=200, msg='获取跟帖失败')





# 更换头像
class QiniuToken(Resource):
    def get(self):
        token = qiniu_token()
        return jsonify(code=200,msg='ok',data={'token':token})




api.add_resource(Register,'/register')  #注册
api.add_resource(SendSMSCode,'/sms_code')   #获取验证码
api.add_resource(Login,'/login')    #登录
api.add_resource(UserInfo,'/userinfo/<int:id>')  #登录用户信息 及 修改
api.add_resource(UserChannels,'/channels')   #用户关注的频道
api.add_resource(Follow_User,'/user_follows')   #登录用户关注的  用户

api.add_resource(Collect_News,'/user_star')   #获取收藏文章
api.add_resource(UserComments,'/user_comments')   #获取用户评论



api.add_resource(QiniuToken,'/qiniu_token')   #七牛云上传头像




